package com.wyk.Spring;

import java.beans.Introspector;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @ClassName: BeanDefinitionReader
 * @Description:
 * @Author: 初久
 * @Date: 2022/7/3 14:21
 **/
public class BeanDefinitionReader {

    private List<String> registryBeanClasses = new ArrayList<>();

    private Properties configProperties = new Properties();

    //固定配置文件中的key，相对于XML的规范
    private final String SCAN_PACKAGE = "scanPackage";

    public BeanDefinitionReader(String... locations) {

        /**
         * @Author 初久
         * @Description 通过URL定位找到其所对应的文件，然后转换为文件流
         * @Date 22:06 2022/7/3
         * @Param [locations]
         * @return
         **/
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:", ""));
        try {
            configProperties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        doScanner(configProperties.getProperty(SCAN_PACKAGE));

    }


    /**
     * @return void
     * @Author 初久
     * @Description 遍历目录下的所有文件和目录
     * @Date 22:02 2022/7/3
     * @Param [scanPackage]
     **/
    private void doScanner(String scanPackage) {

        //转换为文件路径，实际上就是把.替换为/
        URL url = this.getClass().getClassLoader().getResource("./" + scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file : classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPackage + "." + file.getName());
            } else {
                if (!file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                registryBeanClasses.add(className);
            }
        }

    }

    public Properties getconfigProperties() {

        return this.configProperties;

    }

    /**
     * @return java.util.List<com.wyk.Spring.BeanDefinition>
     * @Author 初久
     * @Description 把配置文件中扫描到的所有配置信息转换为BeanDefinition对象，以便于之后的IoC操作
     * tips:我在BeanDefinition中加入了lazyInit属性
     * 后续想要加入懒加载机制可以从这方面入手，现在不需要我就不加了
     * @Date 22:01 2022/7/3
     * @Param []
     **/
    public List<BeanDefinition> loadBeanDefinitions() {

        List<BeanDefinition> result = new ArrayList<>();
        try {

            for (String className : registryBeanClasses) {
                Class<?> beanClass = Class.forName(className);
                if (beanClass.isInterface()) {
                    continue;
                }

                // 扫描所有并添加组件到BeanDefinition中
                if (beanClass.isAnnotationPresent(Component.class)) {


                    if (BeanPostProcessor.class.isAssignableFrom(beanClass)) {
                        result.add(doCreateBeanDefinition(beanClass, decapitalizeName(beanClass.getSimpleName())));
                        continue;
                    }

                    if (beanClass.isAnnotationPresent(Scope.class)) {
                        result.add(doCreateBeanDefinition(beanClass, decapitalizeName(beanClass.getSimpleName()), beanClass.getAnnotation(Scope.class).value()));
                    } else {
                        // 默认为单例模式
                        result.add(doCreateBeanDefinition(beanClass, decapitalizeName(beanClass.getSimpleName())));
                    }
                }
                // 注册Configuration配置类中的bean对象
                registryBeans(beanClass, result);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;

    }

    /**
     * @return void
     * @Author 初久
     * @Description //TODO
     * @Date 22:07 2022/7/3
     * @Param [beanClass, result]
     **/
    public void registryBeans(Class<?> beanClass, List<BeanDefinition> result) {
        if (beanClass.isAnnotationPresent(Configuration.class)) {
            for (Method method : beanClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(Bean.class)) {
                    result.add(doCreateBeanDefinition(method.getReturnType(), method.getName()));
                }
            }
        }
    }


    /**
     * @return com.wyk.Spring.BeanDefinition
     * @Author 初久
     * @Description 把每一个配置信息解析成一个BeanDefinition
     * @Date 22:07 2022/7/3
     * @Param [clazz, factoryBeanName]
     **/
    private BeanDefinition doCreateBeanDefinition(Class<?> clazz, String factoryBeanName) {
        return new BeanDefinition(clazz, factoryBeanName);
    }

    /**
     * @return com.wyk.Spring.BeanDefinition
     * @Author 初久
     * @Description 把每一个配置信息解析成一个BeanDefinition
     * @Date 22:07 2022/7/3
     * @Param [clazz, factoryBeanName, scope]
     **/
    private BeanDefinition doCreateBeanDefinition(Class<?> clazz, String factoryBeanName, String scope) {
        return new BeanDefinition(clazz, factoryBeanName, scope);
    }

    /**
     * @return java.lang.String
     * @Author 初久
     * @Description 格式化类名
     * @Date 22:07 2022/7/3
     * @Param [simpleName]
     **/
    private String decapitalizeName(String simpleName) {
        return Introspector.decapitalize(simpleName);
    }

}